home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / CMDPARSE.C < prev    next >
C/C++ Source or Header  |  1989-09-23  |  6KB  |  218 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "cmdparse.h"
  9.  
  10. int
  11. cmdparse(cmds,line)
  12. struct cmds cmds[];
  13. register char *line;
  14. {
  15.     register char *pp,*rp,*ep,*vp;
  16.     char *cp,*argv[NARG],*getenv();
  17.     static char pool[POOLSIZE];
  18.     int argc,quote;
  19.     char c;
  20.     
  21.     /* Remove cr/lf */
  22.     rip(line);
  23.  
  24.     for(argc = 0;argc < NARG;argc++)
  25.         argv[argc] = NULLCHAR;
  26.  
  27.     pp = pool;
  28.  
  29.     for(argc = 0;argc < NARG && *line != '\0';){
  30.         quote = 0;
  31.         /* Skip leading white space */
  32.         while(*line == ' ' || *line == '\t')
  33.         line++;
  34.         if(*line == '\0')
  35.         break;
  36.         /* Check for quoted token */
  37.         if(*line == '"' || *line == '\'')
  38.         quote = *line++;    /* Suppress quote, remember it */
  39.         argv[argc++] = line;    /* Beginning of token */
  40.         /* Find terminating delimiter */
  41.         if(quote){
  42.         /* Find quote, it must be present */
  43.         if((line = index(line,quote)) == NULLCHAR)
  44.             return -1;
  45.  
  46.         *line++ = '\0';
  47.         } else {
  48.         /* Find space or tab. If not present,
  49.          * then we've already found the last
  50.          * token.
  51.          */
  52.         for (cp = line; *cp; cp++)
  53.             if (*cp == ' ' || *cp == '\t')
  54.             break;
  55.         if (*cp != '\0')
  56.             *cp++ = '\0';
  57.         line = cp;
  58.         }
  59.         /* Check for variablename */
  60.         if(quote != '\'' && index(cp = argv[argc - 1],'$') != NULLCHAR){
  61.         argv[argc - 1] = pp;
  62.         while (*cp != '\0') {
  63.             if (*cp != '$')
  64.             *pp++ = *cp++;
  65.             else {
  66.             if (*++cp == '{') {
  67.                 if ((ep = index(++cp,'}')) == NULLCHAR)
  68.                 return -1;
  69.                 *ep++ = '\0';
  70.             } else {
  71.                 ep = NULLCHAR;
  72.             }
  73.             /* Scan to end of varname and mark it */
  74.             for (vp = cp; isalnum(*vp) || *vp == '_'; vp++)
  75.                 *vp = toupper(*vp);
  76.             /* If a name found, get value */
  77.             if (vp != cp){
  78.                 c = *vp;            /* save next and make \0 */
  79.                 *vp = '\0';
  80.                 rp = getenv(cp);
  81.                 *vp = c;            /* restore next character */
  82.                 if (ep == NULLCHAR){    /* no braces */
  83.                 if (rp == NULLCHAR)    /* undef'd var */
  84.                     rp = "";        /* then just empty */
  85.                 } else {
  86.                 if (rp == NULLCHAR)    /* undef'd var */
  87.                     switch (c) {    /* else look at next */
  88.                     case '=':
  89.                     dosetenv(2,(&cp)-1);/* assign and subst */
  90.                     case '-':
  91.                     rp = vp + 1;    /* subst next word */
  92.                     break;
  93.                     case '?':
  94.                     if (*++vp == '\0')
  95.                     vp = "undefined variable";
  96.                     printf("%s\n",vp);
  97.                     return -1;
  98.                     default:
  99.                     rp = "";    /* default is empty */
  100.                     }
  101.                 else
  102.                     if (c == '+')    /* defined and subst */
  103.                     rp = vp + 1;
  104.                 }
  105.                 /* Copy the result to the pool */
  106.                 while ((*pp++ = *rp++) != '\0')
  107.                 ;
  108.                 pp--;
  109.                 cp = vp;
  110.             }
  111.             if (ep != NULLCHAR)
  112.                 cp = ep;
  113.             }
  114.         }
  115.         *pp++ = '\0';
  116.         if (pp > pool + POOLSIZE){    /* check pool overflow */
  117.             printf("PANIC: pool overflow\n");
  118.             fflush(stdout);
  119.             for (;;)            /* dangerous to continue */
  120.             ;
  121.         }
  122.         }
  123.     }
  124.     if (argc < 1) {            /* empty command line */
  125.         argc = 1;
  126.         argv[0] = "";
  127.     }
  128.     /* Lines beginning with "#" are comments */
  129.     if(argv[0][0] == '#')
  130.         return 0;
  131.  
  132.     return docmd(cmds,argc,argv);    /* execute command */
  133. }
  134.  
  135. /* Call a command based on the first token in an already-parsed line */
  136. int
  137. docmd(tab,argc,argv)
  138. struct cmds tab[];
  139. int argc;
  140. char *argv[];
  141. {
  142.     register struct cmds *cmdp;
  143.     int rslt;
  144.  
  145.     /* Look up command in table; prefix matches are OK */
  146.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  147.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  148.             break;
  149.     }
  150.     if(cmdp->name == NULLCHAR) {
  151.         if(cmdp->argc_errmsg != NULLCHAR)
  152.             printf("%s\n",cmdp->argc_errmsg);
  153.         return -1;
  154.     }
  155.     if(argc < cmdp->argcmin) {
  156.         /* Insufficient arguments */
  157.         printf("Usage: %s %s\n",cmdp->name,cmdp->argc_errmsg);
  158.         return -1;
  159.     }
  160.     argv[0] = cmdp->name;
  161.     rslt = (*cmdp->func)(argc,argv);
  162.     if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
  163.         printf("%s\n",cmdp->exec_errmsg);
  164.     return(rslt);
  165. }
  166.  
  167. /* Call a subcommand based on the first token in an already-parsed line */
  168. int
  169. subcmd(tab,argc,argv)
  170. struct cmds tab[];
  171. int argc;
  172. char *argv[];
  173. {
  174.     int rslt,len;
  175.     register struct cmds *cmdp;
  176.  
  177.     /* Strip off first token and pass rest of line to subcommand */
  178.     if (argc < 2) {
  179.         if (argc < 1)
  180.             printf("SUBCMD - Don't know what to do?\n");
  181.         else
  182.             printf("\"%s\" - takes at least one argument\n",argv[0]);
  183.         return -1;
  184.     }
  185.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  186.         if(strncmp(argv[1],cmdp->name,strlen(argv[1])) == 0){
  187.             if(--argc < cmdp->argcmin) {
  188.                 if (cmdp->argc_errmsg != NULLCHAR)
  189.                     printf("Usage: %s %s %s\n",
  190.                            argv[0],cmdp->name,cmdp->argc_errmsg);
  191.                 return -1;
  192.             }
  193.             (++argv)[0] = cmdp->name;
  194.             rslt = (*cmdp->func)(argc,argv);
  195.             if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
  196.                 printf("%s\n",cmdp->exec_errmsg);
  197.             return(rslt);
  198.         }
  199.     }
  200.     if (cmdp->argc_errmsg != NULLCHAR){
  201.         if (cmdp->argc_errmsg[0] != '?'){
  202.             printf("%s\n",cmdp->argc_errmsg);
  203.         } else {
  204.             printf("%s %s:",argv[0],cmdp->argc_errmsg + 1);
  205.             len = strlen(argv[0]) + strlen(cmdp->argc_errmsg) + 1;
  206.             for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  207.                 if ((len += strlen(cmdp->name) + 1) > 79){
  208.                     len = strlen(cmdp->name) + 9;
  209.                     printf("\n        ");
  210.                 }
  211.                 printf(" %s",cmdp->name);
  212.             }
  213.             printf("\n");
  214.         }
  215.     }
  216.     return -1;
  217. }
  218.